package cn.dakaqi.services.impl;

import cn.dakaqi.dao.ActivityApplyDao;
import cn.dakaqi.entities.Activity;
import cn.dakaqi.entities.ActivityApply;
import cn.dakaqi.entities.GroupVolunteer;
import cn.dakaqi.entities.user.Volunteer;
import cn.dakaqi.enumerate.CommonStatusCode;
import cn.dakaqi.services.ActivityApplyService;
import cn.dakaqi.services.ActivityService;
import cn.dakaqi.services.GroupVolunteerService;
import cn.dakaqi.services.LogService;
import cn.dakaqi.services.user.VolunteerService;
import cn.dakaqi.utils.Clock;
import cn.dakaqi.utils.DKQConstant;
import cn.dakaqi.utils.DateUtil;
import cn.dakaqi.utils.ErrorCodeMsg;
import cn.dakaqi.utils.exception.ServiceRuntimeException;
import cn.dakaqi.utils.rongYun.PushActivityMesssage;
import cn.dakaqi.utils.rongYun.PushGroupMesssage;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author chunyang on 2016/4/17.
 */
@Component(value = "activityApplyService")
@Transactional
public class ActivityApplyServiceImpl implements ActivityApplyService
{
    @Autowired
    GroupVolunteerService groupVolunteerService;
    @Autowired
    ActivityApplyDao activityApplyDao;
    @Autowired
    VolunteerService volunteerService;
    @Autowired
    ActivityService activityService;
    @Autowired
    private LogService logService;

    private void saveLog(String message)
    {
        logService.save(300,message);
    }
    @Override
    public void save(String param) throws ServiceRuntimeException
    {
//        JSONObject jsonObject = JSON.parseObject(param);
//        String memberCode = jsonObject.getString("memberCode");
//        String activityCode = jsonObject.getString("activityCode");
//        int role = jsonObject.getIntValue("role");
//
//        ActivityApply activityApply = new ActivityApply();
//        activityApply.setCreateTime(Clock.DEFAULT.getCurrentDate());
//
//        Volunteer volunteer = volunteerService.findByMemberCode(memberCode);
//        if(Volunteer.checkInfo(volunteer) == false)
//            throw new ServiceRuntimeException(ErrorCodeMsg.USER_INFO_NOT_FULL);
//
//        activityApply.setVolunteer(volunteer);
//        activityApply.setActivity(activityService.findByActivityCode(activityCode));
//        activityApply.setRole(role);
//        activityApply.setStatus(DKQConstant.APPLY_STATUS_OK);
//        this.save(activityApply);

        JSONObject jsonObject = JSON.parseObject(param);
        String memberCode = jsonObject.getString("memberCode");
        String activityCode = jsonObject.getString("activityCode");
        int role = jsonObject.getIntValue("role");

        Activity activity = activityService.findByActivityCode(activityCode);
        ActivityApply activityApply = new ActivityApply();
        activityApply.setCreateTime(Clock.DEFAULT.getCurrentDate());
        //检查当前用户是否已完善个人资料
        Volunteer volunteer = volunteerService.findByMemberCode(memberCode);
        if (!Volunteer.checkInfo(volunteer)) {
            throw new ServiceRuntimeException(CommonStatusCode.USER_INFO_NOT_FULL.getStatusCode(),
                    CommonStatusCode.USER_INFO_NOT_FULL.getStatusMessage());
        }
        //检查当前活动是否已发布对外招募
        if(activity.getActStatus() == DKQConstant.ACT_STATUS_INNER)
        {
            //检查当前用户是否本社团成员
            GroupVolunteer groupVolunteer = this.groupVolunteerService.findByMemberAndGroup(memberCode,DKQConstant.APPLY_STATUS_FREEZE,activity.getGroup().getGroupCode());
            if(null == groupVolunteer)
            {
                throw new ServiceRuntimeException("已被冻结,不可以报名本社团活动");
            }

            groupVolunteer = this.groupVolunteerService.findByMemberAndGroup(memberCode,DKQConstant.APPLY_STATUS_OK,activity.getGroup().getGroupCode());
            if(null == groupVolunteer){
                throw new ServiceRuntimeException(CommonStatusCode.VOLUNTEER_GROUP_REL_NOT_EXISTS.getStatusCode(),
                        CommonStatusCode.VOLUNTEER_GROUP_REL_NOT_EXISTS.getStatusMessage());
            }
        }

        activityApply.setVolunteer(volunteer);
        activityApply.setActivity(activity);
        activityApply.setRole(role);
        activityApply.setStatus(DKQConstant.APPLY_STATUS_OK);
        this.save(activityApply);

    }

    @Override
    public void apply(String param) throws ServiceRuntimeException
    {
        JSONObject jsonObject = JSON.parseObject(param);
        String memberCode = jsonObject.getString("memberCode");
        String activityCode = jsonObject.getString("activityCode");
        int role = jsonObject.getIntValue("role");

        Activity activity = activityService.findByActivityCode(activityCode);
        ActivityApply activityApply = new ActivityApply();
        activityApply.setCreateTime(Clock.DEFAULT.getCurrentDate());
        //检查当前用户是否已完善个人资料
        Volunteer volunteer = volunteerService.findByMemberCode(memberCode);
        if (!Volunteer.checkInfo(volunteer)) {
            throw new ServiceRuntimeException(CommonStatusCode.USER_INFO_NOT_FULL.getStatusCode(),
                    CommonStatusCode.USER_INFO_NOT_FULL.getStatusMessage());
        }
        activityApply.setStatus(DKQConstant.APPLY_STATUS);
        //检查当前活动是否已发布对外招募
        if(activity.getActStatus() == DKQConstant.ACT_STATUS_INNER)
        {
            //检查当前用户是否本社团成员
            GroupVolunteer groupVolunteer = this.groupVolunteerService.findByMemberAndGroup(memberCode,DKQConstant.APPLY_STATUS_ALL,activity.getGroup().getGroupCode());
            if(null != groupVolunteer && groupVolunteer.getStatus() == DKQConstant.APPLY_STATUS_FREEZE)
            {
                throw new ServiceRuntimeException(ErrorCodeMsg.VOLUNTEER_GROUP_FREEZE.getMsg_id(),ErrorCodeMsg.VOLUNTEER_GROUP_FREEZE.getMsg());
            }

            if(null != groupVolunteer && groupVolunteer.getStatus() != DKQConstant.APPLY_STATUS_OK){
                throw new ServiceRuntimeException(CommonStatusCode.VOLUNTEER_GROUP_REL_NOT_EXISTS.getStatusCode(),
                        CommonStatusCode.VOLUNTEER_GROUP_REL_NOT_EXISTS.getStatusMessage());
            }
            activityApply.setStatus(DKQConstant.APPLY_STATUS_OK);
        }
        activityApply.setVolunteer(volunteer);
        activityApply.setActivity(activity);
        activityApply.setRole(role);
        this.save(activityApply);
    }

    @Override
    public ActivityApply save(ActivityApply activityApply) throws ServiceRuntimeException
    {
        //检查当前活动的是否已结束或已被封存
        if(activityApply.getActivity().getActStatus() == DKQConstant.ACT_STATUS_END)
            throw new ServiceRuntimeException("活动已结束,不可以报名参加");
        if(activityApply.getActivity().getLocked() == DKQConstant.ACTIVITY_LOCK)
            throw new ServiceRuntimeException("活动已被封存,不可以报名参加");

        //检查活动报名名额是否已满
        if(activityApply.getActivity().getNeeds()>0)
        {
            int applys = this.activityApplyDao.countByActivity(activityApply.getActivity().getId());
            if(applys>= activityApply.getActivity().getNeeds())
                throw new ServiceRuntimeException("名额已满");
        }

        //检查当前用户是否已报过名,并且各个活动不能有时间上的重叠
        Page<ActivityApply> data = this.queryByMemberAndActivityNotEND(activityApply.getVolunteer().getMemberCode(), 1);
        if(null != data)
        {
            List<ActivityApply> list = data.getContent();
            if(null != list && list.size()>0)
            {
                for(ActivityApply aa:list)
                {
                    if(aa.getActivity().getDelStatus() == DKQConstant.DEL_NO && (aa.getStatus() == DKQConstant.APPLY_STATUS_OK || aa.getStatus() == DKQConstant.APPLY_STATUS))
                    if(DateUtil.isOverLaps(aa.getActivity().getStartTime(), aa.getActivity().getEndTime(), activityApply.getActivity().getStartTime(), activityApply.getActivity().getEndTime(), "yyyy-MM-dd HH:mm") == true)
                    {
                        throw new ServiceRuntimeException("当前活动时间和已报名的活动时间上有重叠,不可以报名");
                    }
                }
            }
        }
        //检查当前用户是否是当前活动的发布者
        if(activityApply.getActivity().getCreateUser().getMemberCode().equals(activityApply.getVolunteer().getMemberCode()))
        {
            activityApply.setRole(DKQConstant.ROLES_CREATEER);
            activityApply.setStatus(DKQConstant.APPLY_STATUS_OK);
        }
        this.activityApplyDao.save(activityApply);
        //活动报名直接通过时，则发送小助手消息
        if(activityApply.getStatus() == DKQConstant.APPLY_STATUS_OK)
        {
            saveLog("用户【" + activityApply.getVolunteer().getId() + "】报名参加了一个活动【" + activityApply.getActivity().getId() + "】" + activityApply.getActivity().getName());
            joinGroupMesssage(activityApply.getVolunteer().getMemberCode(), activityApply.getVolunteer().getNickName(), activityApply.getActivity().getActivityCode(), activityApply.getActivity().getName());
            //更新活动的报名人数
            if (activityApply.getStatus() == DKQConstant.APPLY_STATUS_OK)
            {
                Activity activity = activityApply.getActivity();
                activity.setApplys(activity.getApplys() + 1);
                this.activityService.update(activity);
            }
        }
        return activityApply;
    }

    private void joinGroupMesssage(String userId,String userName,String groupCode,String groupName)
    {
        PushGroupMesssage.getInstance().joinGroup("A",userId, userName,groupCode, groupName);
    }
    private void quitGroupMesssage(String userId,String groupCode)
    {
        PushGroupMesssage.getInstance().quitGroup(userId, groupCode);
    }
    @Override
    public void update(ActivityApply activityApply) throws ServiceRuntimeException
    {
        activityApplyDao.save(activityApply);
    }

    @Override
    public void exit(String param) throws ServiceRuntimeException
    {
        JSONObject jsonObject = JSON.parseObject(param);
        String memberCode = jsonObject.getString("memberCode");
        String activityCode = jsonObject.getString("activityCode");
        String cause = jsonObject.getString("cause");
        ActivityApply activityApply = findByVolunteerAndActivityAndStatus(memberCode, activityCode, DKQConstant.APPLY_STATUS);
        if(null == activityApply)
        {
            activityApply = findByVolunteerAndActivityAndStatus(memberCode, activityCode, DKQConstant.APPLY_STATUS_OK);
            if(null != activityApply)
            {
                activityApply.setRefuseCase(cause);
            }
            else
                throw new ServiceRuntimeException("您没有报名此次活动");
        }
        else
        {
            activityApply.setRefuseCase(cause);
        }

        this.exit(activityApply);
    }

    @Override
    public void exit(ActivityApply activityApply) throws ServiceRuntimeException
    {
        if(null != activityApply)
        {
            //查询活动的状态
            if(activityApply.getActivity().getActStatus() != DKQConstant.ACT_STATUS_INNER && activityApply.getActivity().getActStatus() != DKQConstant.ACT_STATUS_OUTER)
                throw new ServiceRuntimeException("退出失败");

            //活动的负责人不可以退出本次活动
            if(activityApply.getVolunteer().equals(activityApply.getActivity().getMonitor()))
                throw new ServiceRuntimeException("负责人不可以退出活动");
            //更新活动的报名人数
            Activity activity = activityApply.getActivity();
            int count = activity.getApplys()-1;
            activity.setApplys(count<=0?0:count);
            quitGroupMesssage(activityApply.getVolunteer().getMemberCode(), activityApply.getActivity().getActivityCode());
            this.activityService.update(activity);
            saveLog("用户【" + activityApply.getVolunteer().getId() + "】退出活动报名【" + activityApply.getActivity().getId() + "】" + activityApply.getActivity().getName() + ",原因是:"+activityApply.getRefuseCase());
            activityApply.setStatus(DKQConstant.APPLY_STATUS_EXIT);
            this.activityApplyDao.save(activityApply);

            List<String> volunteers = new ArrayList<String>();
            volunteers.add(activityApply.getActivity().getMonitor().getMemberCode());
            PushActivityMesssage.getInstance().exitActivityApply(activityApply.getVolunteer().getRealName(),activityApply.getActivity().getName(),activityApply.getRefuseCase(),volunteers);
            PushGroupMesssage.getInstance().quitGroup(activityApply.getVolunteer().getMemberCode(),"A|"+activityApply.getActivity().getActivityCode());
            //this.activityApplyDao.delete(activityApply);
        }
        else
            throw new ServiceRuntimeException("退出失败");
    }

    @Override
    public void del(Long id) throws ServiceRuntimeException
    {
        ActivityApply activityApply = this.activityApplyDao.findOne(id);
        if(null != activityApply)
        {
            activityApply.setDelStatus(DKQConstant.DEL_YES);
            this.activityApplyDao.save(activityApply);
            saveLog("用户【"+activityApply.getVolunteer().getId()+"】退出活动报名【"+activityApply.getActivity().getId()+"】"+activityApply.getActivity().getName());
            //更新活动的报名人数
            Activity activity = activityApply.getActivity();
            activity.setApplys(activity.getApplys()-1);
            this.activityService.update(activity);
            quitGroupMesssage(activityApply.getVolunteer().getMemberCode(),activityApply.getActivity().getActivityCode());
        }
    }

    @Override
    public void verfier(String memberCode,Long id, int status,String cause) throws ServiceRuntimeException
    {
        ActivityApply activityApply = this.activityApplyDao.findOne(id);
        if(null != activityApply)
        {
            activityApply.setStatus(status);
            activityApply.setRefuseCase(cause);
            this.activityApplyDao.save(activityApply);
            if(status == DKQConstant.APPLY_STATUS_OK)
            {
                joinGroupMesssage(activityApply.getVolunteer().getMemberCode(),activityApply.getVolunteer().getNickName(),activityApply.getActivity().getActivityCode(),activityApply.getActivity().getName());
            }
            saveLog("管理员【"+memberCode+"】审核 【"+activityApply.getVolunteer().getId()+"】报名【"+activityApply.getActivity().getId()+"】"+activityApply.getActivity().getName()+",审核结果为"+status);
        }
    }

    @Override
    public Page<ActivityApply> queryByMember(String memberCode, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.ASC, "activity.orderNum","activity.startTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("volunteer.memberCode", new SearchFilter("volunteer.memberCode", SearchFilter.Operator.EQ, memberCode));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        filters.put("activity.delStatus", new SearchFilter("activity.delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        return this.activityApplyDao.findAll(spec, pageRequest);
    }

    @Override
    public Page<ActivityApply> queryByMember(String memberCode, int status, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.ASC, "activity.orderNum","activity.startTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);

        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("volunteer.memberCode", new SearchFilter("volunteer.memberCode", SearchFilter.Operator.EQ, memberCode));
        filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        return this.activityApplyDao.findAll(spec, pageRequest);
    }


    @Override
    public Page<ActivityApply> queryByActivity(String activityCode, int status, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.ASC, "activity.orderNum","activity.startTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);

        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("activity.activityCode", new SearchFilter("activity.activityCode", SearchFilter.Operator.EQ, activityCode));
        filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        return this.activityApplyDao.findAll(spec, pageRequest);
    }
    @Override
    public Page<ActivityApply> queryAllByActivity(String activityCode, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.ASC, "activity.orderNum","activity.startTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("activity.activityCode", new SearchFilter("activity.activityCode", SearchFilter.Operator.EQ, activityCode));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, DKQConstant.APPLY_STATUS_OK));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        return this.activityApplyDao.findAll(spec, pageRequest);
    }

    @Override
    public void verfier(String param) throws ServiceRuntimeException
    {
        JSONObject jsonObject = JSON.parseObject(param);
        String memberCode = jsonObject.getString("memberCode");
        Long activityApplyId = jsonObject.getLong("activityApplyId");
        int status = jsonObject.getIntValue("status");
        String cause = jsonObject.getString("cause");
        this.verfier(memberCode,activityApplyId, status,cause);
    }

    @Override
    public void setAdmin(String param) throws ServiceRuntimeException
    {
        JSONObject jsonObject = JSON.parseObject(param);
        Long activityApplyId = jsonObject.getLong("activityApplyId");
        String memberCode = jsonObject.getString("memberCode");
        int role = jsonObject.getIntValue("role");
        this.setAdmin(activityApplyId,role,memberCode);
    }

    @Override
    public void setAdmin(Long id, int role,String memberCode) throws ServiceRuntimeException
    {
        ActivityApply activityApply  = this.activityApplyDao.findOne(id);
        if(null != activityApply)
        {
            activityApply.setRole(role);
            this.activityApplyDao.save(activityApply);

            saveLog("管理员【"+memberCode+"】设置用户【"+activityApply.getVolunteer().getId()+"】为活动【"+activityApply.getActivity().getId()+"】"+activityApply.getActivity().getName() + "的管理员，设置状态为"+ role);

            if (role == DKQConstant.ROLES_ADMIN)
            {
                PushActivityMesssage.getInstance().setActivityMonitor(activityApply.getActivity().getName(),activityApply.getVolunteer().getMemberCode(),activityApply.getActivity().getActivityCode());
            }
        }
    }
    @Override
    public Page<ActivityApply> queryByMemberAndActivityNotEND(String memberCode, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.ASC, "activity.orderNum","activity.startTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);

        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("volunteer.memberCode", new SearchFilter("volunteer.memberCode", SearchFilter.Operator.EQ, memberCode));
        filters.put("activity.actStatus", new SearchFilter("activity.actStatus", SearchFilter.Operator.LT, DKQConstant.ACT_STATUS_END));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        return this.activityApplyDao.findAll(spec, pageRequest);
    }

    @Override
    public ActivityApply findByVolunteerAndActivity(Volunteer volunteer, Activity activity) throws ServiceRuntimeException
    {
        return findByVolunteerAndActivity(volunteer.getMemberCode(),activity.getActivityCode());
    }

    @Override
    public ActivityApply findByVolunteerAndActivity(String memberCode, String activityCode) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("volunteer.memberCode", new SearchFilter("volunteer.memberCode", SearchFilter.Operator.EQ, memberCode));
        filters.put("activity.activityCode", new SearchFilter("activity.activityCode", SearchFilter.Operator.EQ, activityCode));
        filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, DKQConstant.APPLY_STATUS_OK));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        List<ActivityApply> list = this.activityApplyDao.findAll(spec);
        if(null != list && list.size()>0)
            return list.get(list.size()-1);
        return null;
    }

    @Override
    public ActivityApply findByVolunteerAndActivityAndStatus(String memberCode, String activityCode, int status) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("volunteer.memberCode", new SearchFilter("volunteer.memberCode", SearchFilter.Operator.EQ, memberCode));
        filters.put("activity.activityCode", new SearchFilter("activity.activityCode", SearchFilter.Operator.EQ, activityCode));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<ActivityApply> spec = DynamicSpecifications.bySearchFilter(filters.values(), ActivityApply.class);
        List<ActivityApply> list = this.activityApplyDao.findAll(spec);
        if(null != list && list.size()>0)
        {
            ActivityApply apply = list.get(list.size()-1);
            if(status == DKQConstant.APPLY_STATUS_ALL)
                return apply;
            else if(apply.getStatus() == status)
            return apply;
        }
        return null;
    }
}
